package com.hhd.pdf.component.table.factory;

import com.hhd.pdf.CommonUtils;
import com.hhd.pdf.component.table.TableBorderHelper;
import com.hhd.pdf.component.table.TableVo;
import com.hhd.pdf.component.table.TdVo;
import com.hhd.pdf.component.table.TrVo;
import com.hhd.pdf.context.GeneratorContext;
import com.hhd.pdf.variable.CompositeFormula;
import com.hhd.pdf.variable.ParsedFormula;
import com.hhd.pdf.variable.VariableContext;
import com.itextpdf.text.pdf.PdfPCell;
import com.itextpdf.text.pdf.PdfPTable;
import org.dom4j.Element;
import org.springframework.stereotype.Component;

import java.util.List;

@Component
public class TableBodyFactory extends TableHeaderFactory {
    @Override
    public void createTableElements(PdfPTable table,
                                    TableVo tableVo,
                                    GeneratorContext context,
                                    TableBorderHelper tableBorderHelper,
                                    Element element) {
        List<TrVo> body = tableVo.getBody();
        if (CommonUtils.isEmpty(body)) return;

        doCreateTableElements(table, tableVo, context, tableBorderHelper);
    }

    private void doCreateTableElements(PdfPTable table,
                                       TableVo tableVo,
                                       GeneratorContext context,
                                       TableBorderHelper tableBorderHelper) {
        deepCreateTrs(context, tableVo, 0, tableBorderHelper, table);
    }

    private void deepCreateTrs(GeneratorContext context,
                               TableVo tableVo,
                               int index,
                               TableBorderHelper tableBorderHelper,
                               PdfPTable table) {
        if (!has(tableVo.getTrs().get(index).getTr(), context)) {
            deepCreateTrs(context, tableVo, index + 1, tableBorderHelper, table);
            return;
        }
        if (index >= tableVo.getBody().size()) {
            return;
        }
        TrVo tr = tableVo.getBody().get(index);
        ParsedFormula formula = getMaxDeepFormula(tr);
        if (CommonUtils.isEmpty(formula)) {
            // 当前是空白行， 没有公式， 直接向下继续渲染即可
            createRow(context, context.getVariableContext(), tableVo, index, tableBorderHelper, table);
            deepCreateTrs(context, tableVo, index + 1, tableBorderHelper, table);
            return;
        }
        //当前不是空白行，先渲染当前行，然后向下渲染即可
        List<VariableContext> variableContexts = getVariableContexts(context, formula, tr);
        for (VariableContext variableContext : variableContexts) {
            GeneratorContext runtime = context.runtime(tr.getTr());
            runtime.getRuntimeData().setVariableContext(variableContext);

            createRow(runtime, variableContext, tableVo, index, tableBorderHelper, table);
            deepCreateTrs(runtime, tableVo, index + 1, tableBorderHelper, table);
        }
    }

    private static List<VariableContext> getVariableContexts(GeneratorContext context, ParsedFormula formula, TrVo tr) {
        if (!CommonUtils.isEmpty(tr.getTr().attributeValue("list"))) {
            return context.getVariableContext().subContextByFormula(formula, false);
        }
        return context.getVariableContext().subContextByFormula(formula);
    }

    private void createRow(GeneratorContext context,
                           VariableContext variableContext,
                           TableVo tableVo,
                           int index,
                           TableBorderHelper tableBorderHelper,
                           PdfPTable table) {
        TrVo trVo = tableVo.getBody().get(index);
        List<TdVo> tds = trVo.getTds();

        for (TdVo td : tds) {
            GeneratorContext runtime = context.runtime(td.getTd());
            runtime.getRuntimeData().setVariableContext(variableContext);

            preResolveTd(td.getTd(), trVo.getTr());
            PdfPCell pdfPCell = buildCell(td, tableBorderHelper, tableVo, runtime);
            List<com.itextpdf.text.Element> elements = genChildren(runtime, td.getTd());
            elements.forEach(pdfPCell::addElement);

            table.addCell(pdfPCell);
        }
        tableBorderHelper.nextRow();
    }

    private void preResolveTd(Element td, Element tr) {
        String s = tr.attributeValue("type");
        if ("header".equals(s)) {
            setDefaultAttribute(td, "type", s);
        }
    }


    private ParsedFormula getMaxDeepFormula(TrVo trVo) {
        Element tr = trVo.getTr();
        String listString = tr.attributeValue("list");
        if (!CommonUtils.isEmpty(listString)) return ParsedFormula.formula(listString);
        CompositeFormula compositeFormula = CompositeFormula.formula(tr.asXML());

        if (CommonUtils.isEmpty(compositeFormula.getFormulas())) return null;
        int deep = -1;
        ParsedFormula res = null;
        for (ParsedFormula formula : compositeFormula.getFormulas()) {
            formula.createVariableFormula();
            if (deep < formula.getVariablePath().getDeep()) {
                deep = formula.getVariablePath().getDeep();
                res = formula;
            }
        }
        return res;
    }
}
